// autostart.go
package main

import (
	"Jam/config"
	"fmt"
	"github.com/axgle/mahonia"
	"golang.org/x/sys/windows"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
)

const (
	taskName = "HEA_Updater"
)

// 提升管理员权限
func isAdmin() bool {
	var sid *windows.SID
	err := windows.AllocateAndInitializeSid(
		&windows.SECURITY_NT_AUTHORITY,
		2,
		windows.SECURITY_BUILTIN_DOMAIN_RID,
		windows.DOMAIN_ALIAS_RID_ADMINS,
		0, 0, 0, 0, 0, 0,
		&sid)
	if err != nil {
		log.Printf("权限检查失败: %v", err)
		return false
	}
	defer windows.FreeSid(sid)

	token := windows.Token(0)
	member, err := token.IsMember(sid)
	if err != nil {
		log.Printf("权限验证失败: %v", err)
		return false
	}
	return member
}

// 增强版开机启动设置
func SetupAutoStart(exePath string) error {
	cfg, _ := config.Load()
	if !cfg.Autostart.Enabled {
		return nil
	}

	log.Printf("开始设置开机启动，程序路径: %s", exePath)

	// 诊断步骤1：检查管理员权限
	if !isAdmin() {
		log.Printf("警告: 当前未以管理员权限运行，可能导致任务创建失败")
	}

	// 诊断步骤2：检查任务是否已存在
	if exists, err := checkTaskExists(); err == nil && exists {
		log.Printf("检测到已存在任务，尝试删除...")
		if err := deleteTask(); err != nil {
			log.Printf("删除旧任务失败: %v", err)
		}
	}

	// 生成明天的15:30作为首次触发时间（保证立即生效）
	now := time.Now().Local()
	firstRun := time.Date(now.Year(), now.Month(), now.Day(), 15, 30, 0, 0, now.Location())
	if now.After(firstRun) {
		firstRun = firstRun.Add(24 * time.Hour)
	}

	// 使用XML方式创建更可靠的任务
	xmlTemplate := fmt.Sprintf(`
    <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
      <RegistrationInfo>
        <Description>医院应急程序HEA定时启动任务</Description>
      </RegistrationInfo>
      <Triggers>
        <LogonTrigger>
          <Enabled>true</Enabled>
        </LogonTrigger>
        <CalendarTrigger>
          <StartBoundary>%s</StartBoundary>
          <Enabled>true</Enabled>
          <ScheduleByDay>
            <DaysInterval>1</DaysInterval>
          </ScheduleByDay>
        </CalendarTrigger>
      </Triggers>
      <Principals>
        <Principal id="Author">
          <UserId>%s</UserId>
          <LogonType>InteractiveToken</LogonType>
          <RunLevel>HighestAvailable</RunLevel>
        </Principal>
      </Principals>
      <Settings>
        <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
        <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
        <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
        <AllowHardTerminate>true</AllowHardTerminate>
        <StartWhenAvailable>true</StartWhenAvailable>
        <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
        <IdleSettings>
          <StopOnIdleEnd>true</StopOnIdleEnd>
          <RestartOnIdle>false</RestartOnIdle>
        </IdleSettings>
        <AllowStartOnDemand>true</AllowStartOnDemand>
        <Enabled>true</Enabled>
        <Hidden>false</Hidden>
        <RunOnlyIfIdle>false</RunOnlyIfIdle>
        <WakeToRun>false</WakeToRun>
        <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
        <Priority>4</Priority>
      </Settings>
      <Actions Context="Author">
        <Exec>
          <Command>"%s"</Command>
          <Arguments>%s</Arguments>
        </Exec>
      </Actions>
    </Task>`,
		firstRun.Format("2006-01-02T15:04:05"), // 使用动态生成的首次运行时间
		getCurrentUser(),
		exePath,
		strings.Join(cfg.Autostart.Args, " "))

	return createTaskWithXML(xmlTemplate)
}

// 使用XML文件创建任务
func createTaskWithXML(xmlContent string) error {
	tmpFile := "task.xml"

	// 修复关键点：将UTF-8字符串转换为GBK编码的字节数组
	encoder := mahonia.NewEncoder("gbk")
	gbkContent := encoder.ConvertString(xmlContent)

	if err := os.WriteFile(tmpFile, []byte(gbkContent), 0644); err != nil {
		return fmt.Errorf("创建临时文件失败: %v", err)
	}
	defer os.Remove(tmpFile)

	cmd := exec.Command("schtasks", "/Create", "/TN", taskName, "/XML", tmpFile, "/F")
	output, err := cmd.CombinedOutput()
	// 转换编码 GBK → UTF-8
	dec := mahonia.NewDecoder("gbk")
	decodedOutput := dec.ConvertString(string(output))

	log.Printf("命令执行: %s\n输出: %s", cmd.String(), decodedOutput)

	if err != nil {
		errorMsg := parseSchTasksError(decodedOutput)
		return fmt.Errorf("任务创建失败: %v\n诊断信息: %s", err, errorMsg)
	}
	return nil
}

// 解析schtasks错误信息
func parseSchTasksError(output string) string {
	msg := output
	switch {
	case strings.Contains(msg, "ERROR: Access is denied"):
		return "权限不足，请以管理员身份运行"
	case strings.Contains(msg, "already exists"):
		return "任务已存在，请先删除旧任务"
	case strings.Contains(msg, "The specified XML file is invalid"):
		return "XML文件格式错误，请检查任务定义"
	case strings.Contains(msg, "The system cannot find the file specified"):
		return "程序路径不存在或不可访问"
	}
	return "未知错误: " + msg
}

// 删除任务
func deleteTask() error {
	cmd := exec.Command("schtasks", "/Delete", "/TN", taskName, "/F")
	output, err := cmd.CombinedOutput()

	// 转换编码格式
	dec := mahonia.NewDecoder("gbk")
	decodedOutput := dec.ConvertString(string(output))
	log.Printf("删除任务命令: %s\n输出: %s", cmd.String(), decodedOutput)
	return err
}

// 获取当前用户名
func getCurrentUser() string {
	var token windows.Token
	process := windows.CurrentProcess()
	err := windows.OpenProcessToken(process, windows.TOKEN_QUERY, &token)
	if err != nil {
		return ""
	}
	defer token.Close()

	user, err := token.GetTokenUser()
	if err != nil {
		return ""
	}
	account, _, _, err := user.User.Sid.LookupAccount("")
	if err != nil {
		return ""
	}
	return account
}

func DeleteAutoStart() error {
	// 检查管理员权限
	if !isAdmin() {
		log.Println("请右键选择'以管理员身份运行'来执行删除操作")
		return nil
	}
	// 检查任务是否存在
	exists, err := checkTaskExists()
	if err != nil {
		return fmt.Errorf("任务状态检查失败: %v", err)
	}
	if !exists {
		log.Println("开机任务不存在，无需删除")
		return nil
	}

	// 执行删除命令
	cmd := exec.Command("schtasks", "/Delete", "/TN", taskName, "/F")
	output, err := cmd.CombinedOutput()

	// 转换编码格式
	dec := mahonia.NewDecoder("gbk")
	decodedOutput := dec.ConvertString(string(output))
	log.Printf("删除命令执行: %s\n输出: %s", cmd.String(), decodedOutput)

	if err != nil {
		return parseDeleteError(decodedOutput, err)
	}
	log.Println("开机任务删除成功")
	return nil
}

// 检查任务是否存在的函数
func checkTaskExists() (bool, error) {
	cmd := exec.Command("schtasks", "/Query", "/TN", taskName)
	output, err := cmd.CombinedOutput()

	// 处理中文编码
	dec := mahonia.NewDecoder("gbk")
	decodedOutput := dec.ConvertString(string(output))

	if err != nil {
		if strings.Contains(decodedOutput, "不存在") {
			return false, nil
		}
		return false, fmt.Errorf("任务查询失败: %v\n%s", err, decodedOutput)
	}
	return true, nil
}

// 解析删除错误信息
func parseDeleteError(output string, originalErr error) error {
	switch {
	case strings.Contains(output, "拒绝访问"):
		return fmt.Errorf("删除失败: 需要管理员权限 (原始错误: %v)", originalErr)
	case strings.Contains(output, "不存在"):
		return fmt.Errorf("删除失败: 任务不存在 (原始错误: %v)", originalErr)
	case strings.Contains(output, "系统找不到指定的文件"):
		return fmt.Errorf("删除失败: 任务名称错误 (原始错误: %v)", originalErr)
	default:
		return fmt.Errorf("删除失败: 未知错误 (%v)\n完整输出: %s", originalErr, output)
	}
}
